package Concurrency2.Chapter03_CAS_Atomic.P01_CASUsage;

import Concurrency2.Chapter03_CAS_Atomic.Utils4Unsafe;
import sun.misc.Unsafe;

/**
 * 测试Unsafe可以修改的内容
 * 1, 实例类型: 普通对象实例 or 类实例;
 * 2, 属性类型: 实例属性 or 静态属性;
 * 3, 属性类型: 普通类型 or Object类型;
 * 测试中使用了自定义的Unsafe工具类.
 */
public class T03_Unsafe {
    public static void main(String[] args) {
        // Step0: 获取Unsafe
        Unsafe unsafe = Utils4Unsafe.getUnsafe();
        // Step1: 获取字段的offset
        long someIntegerOffset;
        long someStringOffset;
        long someStaticIntegerOffset;
        try {
            someIntegerOffset = unsafe.objectFieldOffset(Some.class.getDeclaredField("someInteger"));
            someStringOffset = unsafe.objectFieldOffset(Some.class.getDeclaredField("someString"));
            someStaticIntegerOffset = unsafe.staticFieldOffset(Some.class.getDeclaredField("someStaticInteger"));
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
        // 准备初始值
        Some some = new Some();
        some.setSomeInteger(1);
        some.setSomeString("A");
        // Step2: CAS修改实例属性值
        unsafe.compareAndSwapLong(some, someIntegerOffset, 1, 2);
        unsafe.compareAndSwapObject(some, someStringOffset, "A", "B");
        unsafe.compareAndSwapObject(some, someIntegerOffset, 1, 2);
        unsafe.compareAndSwapObject(Some.class, someStaticIntegerOffset, 1, 2);
        // 验证修改
        System.out.println(some);
        System.out.println(Some.someStaticInteger);
    }

    static class Some {
        private String someString;
        private Integer someInteger;
        public static Integer someStaticInteger = 1;

        public String getSomeString() {
            return someString;
        }

        public void setSomeString(String someString) {
            this.someString = someString;
        }

        public Integer getSomeInteger() {
            return someInteger;
        }

        public void setSomeInteger(Integer someInteger) {
            this.someInteger = someInteger;
        }

        @Override
        public String toString() {
            return "Some{" +
                    "someString='" + someString + '\'' +
                    ", someInteger=" + someInteger +
                    '}';
        }
    }
}
